package com.ruoyi.web.cp.service.http;

import cn.hutool.core.io.FileUtil;
import com.alibaba.fastjson.JSONObject;
import com.ruoyi.web.core.config.ConfigLoader;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.stream.Collectors;

/**
 * @author xiesm
 * &#064;Description:  TODO
 * @date 2025-11-07 18:46
 */
@Slf4j
@Service
public class RmCookieService {
    @Autowired
    private ConfigLoader configLoader;
    // 在类中添加以下成员变量
    private final Map<String, Long> unavailableCookies = new ConcurrentHashMap<>();
    private static final long SILENCE_PERIOD = 60 * 60 * 1000; // 1小时静默期


    public JSONObject getRmHeaders() {
        List<String> availableCookies = getAvailableCookies();

        if (availableCookies.isEmpty()) {
            // 如果没有可用cookie，清除不可用记录重新尝试
            unavailableCookies.clear();
            availableCookies = getAllCookies();
        }

        CookieSelection selection = selectCookie(availableCookies);
        String selectedCookie = selection.getCookie();

        // 可以在这里存储当前使用的cookie信息，用于后续标记不可用
        JSONObject header = new JSONObject();
        header.put("cookie", selectedCookie);
        return header;
    }


    private List<String> getAllCookies() {
        List<String> cookies = new ArrayList<>();

        // 读取两个cookie文件
        for (int i = 1; i <= 2; i++) {
            String filePath = configLoader.getGamenamesPath() + "rm-cookie" + i + ".txt";
            try {
                if (FileUtil.exist(filePath)) {
                    String fileCookie = FileUtil.readString(filePath, "utf8");
                    cookies.add(fileCookie);
                }
            } catch (Exception e) {
                log.warn("Failed to read cookie file: {}", filePath, e);
            }
        }

        return cookies;
    }

    private List<String> getAvailableCookies() {
        List<String> allCookies = getAllCookies();
        long currentTime = System.currentTimeMillis();

        return allCookies.stream()
                .filter(cookie -> {
                    Long unavailableTime = unavailableCookies.get(cookie);
                    return unavailableTime == null || (currentTime - unavailableTime) > SILENCE_PERIOD;
                })
                .collect(Collectors.toList());
    }

    /**
     * 从可用的cookie列表中选择一个cookie
     *
     * @param availableCookies 可用的cookie列表
     * @return 选中的cookie字符串，如果列表为空则返回空字符串
     */
    private volatile int cookieIndex = 0;

    // 创建一个包装类来同时返回cookie值和索引
    private static class CookieSelection {
        private final String cookie;
        private final int index;

        public CookieSelection(String cookie, int index) {
            this.cookie = cookie;
            this.index = index;
        }

        public String getCookie() {
            return cookie;
        }

        public int getIndex() {
            return index;
        }
    }

    /**
     * 从可用的cookie列表中选择一个cookie
     * 采用轮询方式选择，每次调用都会选择下一个cookie
     *
     * @param availableCookies 可用的cookie列表
     * @return CookieSelection对象，包含选中的cookie值和索引；如果列表为空则返回空字符串和-1
     */
    private CookieSelection selectCookie(List<String> availableCookies) {
        // 如果有可用的cookie，则按轮询方式选择一个
        if (!availableCookies.isEmpty()) {
            int selectedIndex = cookieIndex % availableCookies.size();
            String selected = availableCookies.get(selectedIndex);
            cookieIndex = (cookieIndex + 1) % availableCookies.size();
            return new CookieSelection(selected, selectedIndex);
        }
        return new CookieSelection("", -1);
    }

    /**
     * 将指定的cookie标记为不可用
     * 通常在cookie失效或出现错误时调用此方法
     *
     * @param cookie 需要标记为不可用的cookie字符串
     */
    public void markCurrentCookieUnavailable(String cookie) {
        unavailableCookies.put(cookie, System.currentTimeMillis());
        log.info("Cookie marked as unavailable: {}", cookie);
    }


}
